package cn.lijiajia3515.cairo.auth.config;

import cn.lijiajia3515.cairo.auth.framework.security.oauth2.server.authorization.jackson2.CairoAuthorizationServerModule;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.security.jackson2.CoreJackson2Module;
import org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module;

@Configuration(proxyBeanMethods = false)
public class RedisConfig {

	@Bean
	@Primary
	RedisSerializer<Object> defaultRedisValueSerializer() {
		ObjectMapper mapper = new ObjectMapper();
		mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.PUBLIC_ONLY);
		mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);


		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

		mapper.registerModule(new JavaTimeModule());
		mapper.registerModule(new CoreJackson2Module());
		mapper.registerModule(new CairoAuthorizationServerModule());
		mapper.registerModule(new OAuth2ClientJackson2Module());
		GenericJackson2JsonRedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer(mapper);
		return valueSerializer;
	}

	@Bean
	RedisTemplate<String, Object> stringObjectRedisTemplate(RedisSerializer<Object> valueSerializer, RedisConnectionFactory factory) {
		final RedisTemplate<String, Object> template = new RedisTemplate<>();

		StringRedisSerializer keyRedisSerializer = new StringRedisSerializer();
		template.setConnectionFactory(factory);

		template.setKeySerializer(keyRedisSerializer);
		template.setHashKeySerializer(keyRedisSerializer);


		template.setValueSerializer(valueSerializer);
		template.setHashValueSerializer(valueSerializer);

		// 开启事务
		template.setEnableTransactionSupport(true);

		template.afterPropertiesSet();
		return template;
	}
}
